package com.k.frame.jvm.gc.dep.control;

import com.k.frame.jvm.gc.dep.util.GCUtil;
import com.k.frame.jvm.gc.dep.vo.ConfigModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

//@RequestMapping(path = "${jvmPre}")
@RestController
public class BootControl {
    @Autowired
    private ConfigModel ret;
    // = new ConfigModel();

    @GetMapping("/")
    public ConfigModel home() {
        return retObj();
    }

    @GetMapping("/randomSleep")
    public ConfigModel randomSleep(@RequestParam int nextNum) throws InterruptedException {
        GCUtil.randomSleep(nextNum);
        return retObj();
    }

    @GetMapping("/random")
    public ConfigModel random() {
        GCUtil.random();
        return retObj();
    }

    @GetMapping("/index")
    public ConfigModel index() {
        new Object();
        return retObj();
    }

    @GetMapping("/gc")
    public ConfigModel gc() {
        GCUtil.xm();
        return retObj();
    }

    @GetMapping("/whiletrue")
    public ConfigModel whiletrue() {
        GCUtil.whiletrue();
        return retObj();
    }

    @GetMapping("/timedWaiting")
    public ConfigModel timedWaiting() throws InterruptedException {
        GCUtil.timedWaiting();
        return retObj();
    }

    @GetMapping("/waiting")
    public ConfigModel waiting() {
        GCUtil.waiting();
        return retObj();
    }

    @GetMapping("/blocked")
    public ConfigModel blocked() {
        GCUtil.blocked();
        return retObj();
    }

    @GetMapping("/runnable")
    public ConfigModel runnable() {
        GCUtil.runnable();
        return retObj();
    }

    @GetMapping("/direct")
    public ConfigModel direct() throws IllegalAccessException {
        int _1MB = 1024 * 1024;
        Field field = Unsafe.class.getDeclaredFields()[0];
        field.setAccessible(true);
        Unsafe unsafe = (Unsafe) field.get(null);
        while (true) {
            unsafe.allocateMemory(_1MB);
        }
    }

    @GetMapping("/oom")
    public ConfigModel oom() {
        class OOMObject {
        }
        List<OOMObject> list = new ArrayList<>();
        while (true) {
            list.add(new OOMObject());
        }
    }

    @GetMapping("/stack")
    public ConfigModel stack() {
        stackLeek();
        return retObj();
    }


    private void stackLeek() {
        stackLeek();
    }

    private void dontStop() {
        while (true) {
        }
    }

    private void stackLeekThread() {
        while (true) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    dontStop();

                }
            });
            thread.start();
        }
    }

    private ConfigModel retObj() {
        return ret;
    }

}
